/*
 *  SVO - Simple Video Out FPGA Core
 *
 *  Copyright (C) 2014  Clifford Wolf <clifford@clifford.at>
 *  
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *  
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

`timescale 1ns / 1ps
`include "svo_defines.vh"

module svo_hdmi_top (
	input clk,
	input resetn,

	// video clocks
	input clk_pixel,
	input clk_5x_pixel,
	input locked,

	input term_in_tvalid,
	output term_out_tready,
	input [7:0] term_in_tdata,

	// output signals
	output       tmds_clk_n,
	output       tmds_clk_p,
	output [2:0] tmds_d_n,
	output [2:0] tmds_d_p
);
	parameter SVO_MODE             =   "640x480V";
	parameter SVO_FRAMERATE        =   60;
	parameter SVO_BITS_PER_PIXEL   =   24;
	parameter SVO_BITS_PER_RED     =    8;
	parameter SVO_BITS_PER_GREEN   =    8;
	parameter SVO_BITS_PER_BLUE    =    8;
	parameter SVO_BITS_PER_ALPHA   =    0;

	localparam [SVO_BITS_PER_PIXEL-1:0] white_pixval = ~0;
	wire [7:0] vga_r;
	wire [7:0] vga_g;
	wire [7:0] vga_b;
	wire vga_hs;
	wire vga_vs;
	wire vga_de;
	wire vdma_tvalid;
	wire vdma_tready;
	wire [SVO_BITS_PER_PIXEL-1:0] vdma_tdata;
	wire [0:0] vdma_tuser;

	wire video_tvalid;
	wire video_tready;
	wire [SVO_BITS_PER_PIXEL-1:0] video_tdata;
	wire [0:0] video_tuser;

	wire term_out_tvalid;
	// wire term_out_tready;
	wire [1:0] term_out_tdata;
	wire [0:0] term_out_tuser;

	wire video_enc_tvalid, video_enc_tready;
	wire [SVO_BITS_PER_PIXEL-1:0] video_enc_tdata;
	wire [3:0] video_enc_tuser;

	wire [2:0] tmds_d;
	wire [2:0] tmds_serdes_shift1;
	wire [2:0] tmds_serdes_shift2;
	wire [2:0] tmds_d0, tmds_d1, tmds_d2, tmds_d3, tmds_d4;
	wire [2:0] tmds_d5, tmds_d6, tmds_d7, tmds_d8, tmds_d9;
	wire [9:0] pixel_xpos;
	wire [9:0] pixel_ypos;
	wire data_req;

	wire clk_pixel_resetn = locked ;

	assign vga_r = (data_req) ? {8{pixel_xpos[4]}} : 8'h0;
	assign vga_g = (data_req) ? {8{pixel_xpos[5]}} : 8'h0;
	assign vga_b = (data_req) ? {8{pixel_xpos[6]}} : 8'h0;
	
	vga_driver vga_driver_u1(
		.clk(clk_pixel),
		.rst_n(clk_pixel_resetn),
		.vga_hs(vga_hs),
		.vga_vs(vga_vs),
		.pixel_xpos(pixel_xpos),
		.pixel_ypos(pixel_ypos),
		.vga_en(vga_de),
		.data_req(data_req)
	);
	assign video_enc_tready = 1;

	svo_tmds svo_tmds_0 (
		.clk(clk_pixel),
		.resetn(clk_pixel_resetn),
		.de(vga_de),
		.ctrl({vga_vs,vga_hs}),
		.din(vga_r),
		.dout({tmds_d9[0], tmds_d8[0], tmds_d7[0], tmds_d6[0], tmds_d5[0],
		       tmds_d4[0], tmds_d3[0], tmds_d2[0], tmds_d1[0], tmds_d0[0]})
	);

	svo_tmds svo_tmds_1 (
		.clk(clk_pixel),
		.resetn(clk_pixel_resetn),
		.de(vga_de),
		.ctrl(2'b0),
		.din(vga_g),
		.dout({tmds_d9[1], tmds_d8[1], tmds_d7[1], tmds_d6[1], tmds_d5[1],
		       tmds_d4[1], tmds_d3[1], tmds_d2[1], tmds_d1[1], tmds_d0[1]})
	);

	svo_tmds svo_tmds_2 (
		.clk(clk_pixel),
		.resetn(clk_pixel_resetn),
		.de(vga_de),
		.ctrl(2'b0),
		.din(vga_b),
		.dout({tmds_d9[2], tmds_d8[2], tmds_d7[2], tmds_d6[2], tmds_d5[2],
		       tmds_d4[2], tmds_d3[2], tmds_d2[2], tmds_d1[2], tmds_d0[2]})
	);
    
	OSER10 tmds_serdes [2:0] (
		.Q(tmds_d),
		.D0(tmds_d0),
		.D1(tmds_d1),
		.D2(tmds_d2),
		.D3(tmds_d3),
		.D4(tmds_d4),
		.D5(tmds_d5),
		.D6(tmds_d6),
		.D7(tmds_d7),
		.D8(tmds_d8),
		.D9(tmds_d9),
		.PCLK(clk_pixel),
		.FCLK(clk_5x_pixel),
		.RESET(~clk_pixel_resetn)
	);
	
	ELVDS_OBUF tmds_bufds [3:0] (
		.I({clk_pixel, tmds_d}),
		.O({tmds_clk_p, tmds_d_p}),
		.OB({tmds_clk_n, tmds_d_n})
	);

endmodule
